

import {parseHTML} from './parser-html';
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g

function genProps(attrs){
  let str = '';
  for(let i=0;i<attrs.length;i++){
    let attr = attrs[i];
    if(attr.name === 'style'){
      //style = "color:red" => {style: {color: 'red'}}
      let obj = {};
      attr.value.split(';').forEach(item=>{
        let [key,value] = item.split(':');
        obj[key] = value;
      })
      attr.value = obj;
    }
    str+= `${attr.name}:${JSON.stringify(attr.value)},`;
  }

  return `{${str.slice(0,-1)}}`;
}

function gen(node){
    if(node.type == 1){
       return generate(node);
    }else {
      let text = node.text; //   <div>a {{  name  }} b{{age}} c</div>
      let tokens = [];
      let match,index;
      // 每次的偏移量 buffer.split()
      let lastIndex = defaultTagRE.lastIndex = 0; // 只要是全局匹配 就需要将lastIndex每次匹配的时候调到0处
      while(match = defaultTagRE.exec(text)){
          index = match.index;
          if(index > lastIndex){
              tokens.push(JSON.stringify(text.slice(lastIndex,index)));
          }
          tokens.push(`_s(${match[1].trim()})`);
          lastIndex = index + match[0].length;
      }
      if(lastIndex < text.length){
          tokens.push(JSON.stringify(text.slice(lastIndex)))
      }
      return `_v(${tokens.join('+')})`;
    }
}

function genChildren(children){
  if(children && children.length){ 
    return `${children.map(c=>gen(c)).join(',')}`;
  }else{
    return false;
  }
}
 
function generate(el){
  let code = `_c("${el.tag}",${
    el.attrs.length?
    genProps(el.attrs): 'undefined'
  },${
    el.children?  genChildren(el.children): ''
  }
  )

  `
  return code;
}
//ast语法树：用对象来描述原生语法的
export function compileToFunction(template){
  // console.log(template,'template2333');
  let root = parseHTML(template);
  // console.log(root,'root')

  let code = generate(root);
  // console.log(code,'code222')
  //核心思路是模版字符串转换
  //<div id="app"><p>hello {{name}}</p>hello</div>
  //_c("div",{id:app},_c("p",undefined,_v('hello'+_s(name) )),_v('hello'));
  let renderFn = new Function(`with(this){return ${code}}`)
  // console.log(renderFn);
  return renderFn;
}


// <div id="app">
//   <p>hello</p>
// </div>

// let root = {
//   tag: 'div',
//   type: 1,
//   attrs:[{name:'id',value:'app'}],
//   parent:null,
//   children: [{
//     tag: 'p',
//     attrs:null,
//     parent: root,
//     children:[{
//       text: 'hello',
//       type:3
//     }]
//   }]
// }